#ifndef __SUBSYSTEM_ADAPTOR_H__
#define __SUBSYSTEM_ADAPTOR_H__

#pragma once

#include "EngineConfig.h"

#if defined NZOS_WIN32
#    define DYNLIB_HANDLE hInstance
#    define DYNLIB_LOAD( a ) LoadLibraryEx( a, NULL, LOAD_WITH_ALTERED_SEARCH_PATH )
#    define DYNLIB_GETENTRY( a, b ) GetProcAddress( a, b )
#    define DYNLIB_UNLOAD( a ) FreeLibrary( a )

struct HINSTANCE__;
typedef struct HINSTANCE__* hInstance;

#elif defined NZOS_ANDROID
#    define DYNLIB_HANDLE void*
#    define DYNLIB_LOAD( a ) dlopen( a, RTLD_LAZY | RTLD_GLOBAL)
#    define DYNLIB_GETENTRY( a, b ) dlsym( a, b )
#    define DYNLIB_UNLOAD( a ) dlclose( a )

#elif defined NZOS_IOS
#    define DYNLIB_HANDLE void*
#    define DYNLIB_LOAD( a ) mac_loadDylib( a )
#    define DYNLIB_GETENTRY( a, b ) dlsym( a, b )
#    define DYNLIB_UNLOAD( a ) dlclose( a )

#endif

namespace Nezha
{

	class NezhaEngine;

	// predefine sub-system types.
	enum Subsystems
	{
		SYS_NETWORK = 0,
		SYS_RENDERER,
		SYS_PHYSICS,
		SYS_SOUND,
		SYS_SCRIPT,
		SYS_LOGICFLOW,

		// number of subsystems
		SYS_NUM,
	};

	class DynamicLibary;

	/** Nezha engine plugin base. */
	class NEZHA_ENGINE_ENTRY SubsystemAdaptor
	{
	public:
		virtual ~SubsystemAdaptor(){}

		virtual Subsystems getType() const  = 0;

		virtual bool initialize(NezhaEngine* engine) = 0;

		virtual void uninitialize() = 0;

		static const _string msCreateEntryName;
		static const _string msDestroyEntryName;
	};

	// plugin entry
	// for create subsystem, use "NezhaPluginCreate"
	// for destroy subsystem, use "NezhaPluginDestroy"
	typedef SubsystemAdaptor* (*NZ_Plugin_Create)(void);
	typedef void (*NZ_Plugin_Destroy)(void);


	/** Dynamic libary wrapper. */
	class NEZHA_ENGINE_ENTRY DynamicLibary
	{
	public:
		DynamicLibary();
		~DynamicLibary();

		bool load(const _string& name);

		void unload();

		void* getProcAddress(const _string& procName);

		const _string& getName() const
		{
			return mName;
		}
	private:
		DYNLIB_HANDLE mHandle;
		_string mName;
	};
}

#endif //end __SUBSYSTEM_ADAPTOR_H__